package cn.edu.fzu.delivery.controller;

import cn.edu.fzu.delivery.cache.IpCache;
import cn.edu.fzu.delivery.common.MD5Util;
import cn.edu.fzu.delivery.common.Result;
import cn.edu.fzu.delivery.common.RetCode;
import cn.edu.fzu.delivery.domain.entity.Customer;
import cn.edu.fzu.delivery.domain.entity.SysUser;
import cn.edu.fzu.delivery.domain.enums.UserStatusEnum;
import cn.edu.fzu.delivery.exception.ServiceException;
import cn.edu.fzu.delivery.helper.VcodeHelper;
import cn.edu.fzu.delivery.service.UserService;
import cn.edu.fzu.delivery.session.SessionConstant;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import com.google.common.collect.Maps;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Map;

import static cn.edu.fzu.delivery.common.RedisKey.vCodeKey;

/**
 * @author fangxin
 * @date 2022/9/8
 */
@RestController
@Api(tags = "登录管理")
public class LoginController {

    @Resource
    private UserService userService;
    @Resource
    private IpCache     ipCache;

    /** 登录 **/
    @PostMapping("/api/sysLogin")
    @ApiOperation(value = "系统人员登录", httpMethod = "POST")
    @ApiImplicitParams({ @ApiImplicitParam(name = "email", required = true),
            @ApiImplicitParam(name = "password", required = true),
            @ApiImplicitParam(name = "code", value = "图片验证码", required = true) })
    public Result login(String email, String password, @RequestParam String code, HttpServletRequest request) {
        HttpSession session = request.getSession();

        String vcode = (String) session.getAttribute(vCodeKey(session.getId()));
        if (!StringUtils.equalsIgnoreCase(code, vcode)) {
            throw new ServiceException(RetCode.PARAMETER_ERROR, "验证码错误");
        }
        SysUser user = userService.getSysUserByEmail(email);
        if (user == null) {
            throw new ServiceException(RetCode.PARAMETER_ERROR, "用户不存在");
        }
        if (user.getStatus() == UserStatusEnum.BAN || user.getStatus() == UserStatusEnum.DELETE) {
            throw new ServiceException(RetCode.REFUSE_LOGIN, "禁止访问");
        }
        if (!user.getPassword().equals(MD5Util.MD5Encode(password))) {
            throw new ServiceException(RetCode.PARAMETER_ERROR, "密码错误");
        }

        //防止被攻击，使用token校验
        String token = MD5Util.MD5Encode(password + System.currentTimeMillis());
        session.setAttribute(SessionConstant.DELIVERY_ACCOUNT, user);
        session.setAttribute(SessionConstant.TOKEN, token);

        Map<String, Object> map = Maps.newHashMapWithExpectedSize(2);
        map.put(SessionConstant.DELIVERY_ACCOUNT, user);
        map.put(SessionConstant.TOKEN, token);
        return new Result(RetCode.SUCCESS, map, "登录成功");
    }


    /** 顾客登录 **/
    @ApiOperation(value = "顾客登录", httpMethod = "POST")
    @ApiImplicitParams({ @ApiImplicitParam(name = "email", required = true),
            @ApiImplicitParam(name = "password", required = true),
            @ApiImplicitParam(name = "code", value = "图片验证码", required = true) })
    @PostMapping("/api/cusLogin")
    public Result cusLogin(String email, String password, @RequestParam String code, HttpServletRequest request) {
        HttpSession session = request.getSession();

        String vcode = (String) session.getAttribute(vCodeKey(session.getId()));
        if (!StringUtils.equalsIgnoreCase(code, vcode)) {
            throw new ServiceException(RetCode.PARAMETER_ERROR, "验证码错误");
        }
        Customer user = userService.getCustomerByEmail(email);
        if (user == null) {
            throw new ServiceException(RetCode.PARAMETER_ERROR, "用户不存在");
        }
        if (user.getStatus() == UserStatusEnum.BAN || user.getStatus() == UserStatusEnum.DELETE) {
            throw new ServiceException(RetCode.REFUSE_LOGIN, "禁止访问");
        }
        if (!user.getPassword().equals(MD5Util.MD5Encode(password))) {
            throw new ServiceException(RetCode.PARAMETER_ERROR, "密码错误");
        }
        String ip = request.getHeader("X-Real-IP");
        //防止被攻击，使用token校验
        String token = MD5Util.MD5Encode(password + System.currentTimeMillis());
        session.setAttribute(SessionConstant.DELIVERY_ACCOUNT, user);
        session.setAttribute(SessionConstant.TOKEN, token);
        session.setAttribute(SessionConstant.CITY, ipCache.getCity(ip));
        Map<String, Object> map = Maps.newHashMapWithExpectedSize(2);
        map.put(SessionConstant.DELIVERY_ACCOUNT, user);
        map.put(SessionConstant.TOKEN, token);
        return new Result(RetCode.SUCCESS, map, "登录成功");
    }


    @ApiOperation(value = "获取当前登录用户实时信息", httpMethod = "GET")
    @GetMapping("/api/auth/getCurrentUserInfo")
    public Result getCurrentUserInfo(HttpServletRequest request) {
        Object o = request.getSession().getAttribute(SessionConstant.DELIVERY_ACCOUNT);
        if (o instanceof SysUser) {
            SysUser user = (SysUser) o;
            return new Result(userService.getSysUserByEmail(user.getEmail()));
        } else if (o instanceof Customer) {
            Customer customer = (Customer) o;
            return new Result(userService.getCustomerByEmail(customer.getEmail()));
        }
        throw new ServiceException("异常登录");
    }


    /** 获取图片验证码 **/
    @GetMapping("/api/codeImg")
    @ApiOperation(value = "获取图片验证码", httpMethod = "GET")
    public Result codeImg(HttpServletRequest request) throws IOException {
        HttpSession session = request.getSession();
        VcodeHelper helper = new VcodeHelper();
        String key = vCodeKey(session.getId());
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        BufferedImage generatorVCodeImage;

        String code = (String) session.getAttribute(key);
        if (StringUtils.isBlank(code)) {
            code = helper.generatorVCode();
        }
        generatorVCodeImage = helper.generatorRotateVCodeImage(code, true);
        ImageIO.write(generatorVCodeImage, "gif", outputStream);
        session.setAttribute(key, code);
        return new Result(Base64.encodeBase64String(outputStream.toByteArray()));

    }


    @GetMapping("/api/logout")
    @ApiOperation(value = "退出登录", httpMethod = "GET")
    public Result logout(HttpServletRequest request) {
        request.getSession().invalidate();
        return Result.SUCCESS;
    }
}
